package ${basepackage}.framework.service;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.dongfang.framework.base.util.AppConstant;
import com.dongfang.framework.base.util.JsonUtil;
import com.dongfang.framework.model.AuditLog;
import com.dongfang.framework.vo.ValueObject;

import ${basepackage}.framework.base.dao.EntityDao;
import ${basepackage}.framework.base.service.BaseServiceImpl;
import ${basepackage}.framework.base.util.AppConstant;
import ${basepackage}.framework.dao.AuditLogDAO;
import ${basepackage}.framework.model.AuditLog;
import ${basepackage}.framework.vo.ValueObject;

@Service
public class AuditLogServiceImpl extends BaseServiceImpl<AuditLog, Long>
		implements AuditLogService {

	@Autowired
	private AuditLogDAO auditLogDAO;
	
	@Override
	public EntityDao getEntityDao() {
		// TODO Auto-generated method stub
		return auditLogDAO;
	}

	public List<ValueObject> getAuditLogDetail(Long auditLogId) throws DataAccessException{
		
		Map<String,String> newMap = new HashMap<String,String>();
		Map<String,String> oldMap = new HashMap<String,String>();
		List<ValueObject> list = new ArrayList<ValueObject>();
		
		ValueObject vo;
		AuditLog auditLog = auditLogDAO.getById(auditLogId);
		if(auditLog != null){
			if(AppConstant.AUDITLOG_ACTION_Deleted.equals(auditLog.getAction())){
				oldMap = parseAuditLogDetail(auditLog.getDetail(),auditLog.getEntityName());
				for(String key:oldMap.keySet()){
					vo = new ValueObject();
					vo.setKey(key);
					vo.setOldValue(oldMap.get(key));
					list.add(vo);
				}
			}else if(AppConstant.AUDITLOG_ACTION_NEW.equals(auditLog.getAction())){
				newMap = parseAuditLogDetail(auditLog.getDetail(),auditLog.getEntityName());
				for(String key:newMap.keySet()){
					vo = new ValueObject();
					vo.setKey(key);
					vo.setNewValue(newMap.get(key));
					list.add(vo);
				}
				
			}else
			{
				AuditLog previousAuditLog = auditLogDAO.getPreviousAuditLog(auditLog);
				if(previousAuditLog != null){
					oldMap = parseAuditLogDetail(previousAuditLog.getDetail(),auditLog.getEntityName());
				}
				newMap = parseAuditLogDetail(auditLog.getDetail(),auditLog.getEntityName());
				
				for(String key:newMap.keySet()){
					vo = new ValueObject();
					vo.setKey(key);
					vo.setNewValue(newMap.get(key));
					vo.setOldValue(oldMap.get(key));
					list.add(vo);
				}
				
			}
		}
		
		
		return list;
		
		
	}
	
	private Map<String,String> parseAuditLogDetail(String detail){
		Map<String,String> map = new HashMap<String,String>();
		if(detail == null || detail.length() <=0){
			return map;
		}
		int index = detail.indexOf("= [");
		if(index < 0){
			index = 0;
		}else{
			index = index + 3;
		}
		detail = detail.substring(index, detail.length() - 1);
		String[] strArray = StringUtils.tokenizeToStringArray(detail, ",");
		if(strArray != null){
			for(int i = 0;i<strArray.length;i++){
				String[] strArray2 = StringUtils.tokenizeToStringArray(strArray[i], ":");
				if(strArray2 != null && strArray2.length> 1){
					map.put(strArray2[0], strArray2[1]);
				}
				
			}
		}
		return map;
	}
	
	private Map<String,String> parseAuditLogDetail(String detail,String className){
		Map<String,String> map = new HashMap<String,String>();
		if(detail == null || detail.length() <=0){
			return map;
		}
		className = className.substring(6);
		try {
			Object bean = JsonUtil.jsonToBean(detail,Class.forName(className));
			PropertyDescriptor[] pds = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
			for(PropertyDescriptor pd:pds){
				Method readMethod = pd.getReadMethod();
				
				String name = pd.getName();
				if(name.equals("logId") || name.equals("logDeatil")){
					continue;
				}
				Object o = readMethod.invoke(bean);
				map.put(name, String.valueOf(o));
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			return parseAuditLogDetail(detail);
		}
		return map;
	}
}
